<?php
/**
 * Created by PhpStorm.
 * User: ari
 * Date: 1/13/2015
 * Time: 7:52 PM
 */
namespace BC\Misc;

use BC\SiteIndex;
use CPath\Build\IBuildable;
use CPath\Build\IBuildRequest;
use CPath\Request\Executable\IExecutable;
use CPath\Request\IRequest;
use CPath\Response\IResponse;
use CPath\Route\IRoutable;
use CPath\Route\RouteBuilder;

class LongPoll implements IBuildable, IRoutable, IExecutable
{
	const PATH = '/poll';
	const COMMAND_PATH = 'path';
	const COMMAND_ERROR = 'error';
	const PARAM_PATH = 'path';

	const POLL_LENGTH = 100;
	const SLEEP_MS = 100;

	/**
	 * Execute a command and return a response. Does not render
	 * @param IRequest $Request
	 * @return IResponse the execution response
	 */
	function execute(IRequest $Request) {
		session_write_close();
		ignore_user_abort(false);

		for($i=0; $i<self::POLL_LENGTH; $i++) {
			clearstatcache();

			$paths = $Request[self::PARAM_PATH];
			if(is_string($paths))
				$paths = explode(';', $paths);
			$found = false;
			foreach ($paths as &$path) {
				if (is_string($path))
					$path = explode(',', $path, 2);
				list($path, $offset) = $path;
				$offset = intval($offset);
				$size = filesize($path);
				if ($size > $offset) {
					$found = true;

					if($handle = @fopen($path, 'r')) {
						fseek($handle, $offset);
						echo self::COMMAND_PATH, ' ', $path, ' ', $size, PHP_EOL;
						fpassthru($handle);
						fclose($handle);
					}
				} elseif ($size < $offset) {

					echo self::COMMAND_ERROR, " Offset is larger than log size. Not good\n";
					echo self::COMMAND_PATH, ' ', $path, ' ', $size, PHP_EOL;
					header("HTTP/1.1 400 Offset is larger than log size. Not good");
					header("Access-Control-Allow-Origin: *");
					die();
				}
			}

			if ($found) {
				header("HTTP/1.1 206 Partial");
				header("Access-Control-Allow-Origin: *");
				die();
			}
			usleep(self::SLEEP_MS * 1000);
		}
		header("HTTP/1.1 206 Unmodified");
		header("Access-Control-Allow-Origin: *");
		die();
	}

	// Static

	/**
	 * Handle this request and render any content
	 * @param IBuildRequest $Request the build request inst for this build session
	 * @return void
	 * @build --disable 0
	 * Note: Use doctag 'build' with '--disable 1' to have this IBuildable class skipped during a build
	 */
	static function handleBuildStatic(IBuildRequest $Request) {
		$RouteBuilder = new RouteBuilder($Request, new SiteIndex(), '_poll');
		$RouteBuilder->writeRoute(self::PATH . '/:' . self::PARAM_PATH, __CLASS__);
	}
	/**
	 * Route the request to this class object and return the object
	 * @param IRequest $Request the IRequest inst for this render
	 * @param array|null $Previous all previous response object that were passed from a handler, if any
	 * @param null|mixed $_arg [varargs] passed by route map
	 * @return void|bool|Object returns a response object
	 * If nothing is returned (or bool[true]), it is assumed that rendering has occurred and the request ends
	 * If false is returned, this static handler will be called again if another handler returns an object
	 * If an object is returned, it is passed along to the next handler
	 */
	static function routeRequestStatic(IRequest $Request, Array &$Previous = array(), $_arg = null) {
		return new LongPoll();
	}
}